<?php

   //include_once(ROOT_PATH . 'data/config.php');
 /**
 *   OPENSHOP 中国银联插件
 *
 *   @link        http://baison.com.cn
 *   @copyright   Baison, Inc.
 *   @package     OpenShop
 *   @version     $Id: unionpay.php,v 1.0.3 20011/04/20 14:12: modified $
 *   @author      Roban Lee <RobanLee@gmail.com>
 */
if (!defined('RUN_FROM_INDEX')){
    die('Access Denied');
}


/* 模块的基本信息 */
if (isset($set_modules) && $set_modules == TRUE)
{
    $i = isset($modules) ? count($modules) : 0;

    $modules[$i]['name']    = '中国银联';

    /* 代码 */
    $modules[$i]['code']    = basename(__FILE__, '.php');

    /* 描述对应的语言项 */
    $modules[$i]['desc']    = '中国银联是经国务院同意，中国人民银行批准设立的中国银行卡联合组织，成立于2002年3月，总部设于上海。目前已拥有近400家境内外成员机构。
';

    /* 是否支持货到付款 */
    $modules[$i]['is_cod']  = '0';

    /* 是否支持在线支付 */
    $modules[$i]['is_online']  = '1';

    /* 作者 */
    $modules[$i]['author']  = 'OpenShop TEAM';

    /* 网址 */
    $modules[$i]['website'] = 'http://cn.unionpay.com/';

    /* 版本号 */
    $modules[$i]['version'] = '1.0.0';

    /* 配置信息 */
    $modules[$i]['config']  = array(
        array('name' => 'merId', 'label' =>'商户号',  'type' => 'text', 'value' => ''),
        array('name' => 'security_key',   'label' =>'商户密钥',    'type' => 'text', 'value' => ''),
        array('name' => 'merAbbr',  'label' =>'商户名称',   'type' => 'text', 'value' => '')
    );

    return;
}

/**
 * 类

 */
class unionpay extends BasePay
{
	private $FRONT_PAY = 1;
    private $BACK_PAY  = 2;
    private $RESPONSE  = 3;
    private $QUERY     = 4;

    private $CONSUME                = "01";
    private $CONSUME_VOID           = "31";
    private $PRE_AUTH               = "02";
    private $PRE_AUTH_VOID          = "32";
    private $PRE_AUTH_COMPLETE      = "03";
    private $PRE_AUTH_VOID_COMPLETE = "33";
    private $REFUND                 = "04";
    private $REGISTRATION           = "71";

    private $CURRENCY_CNY = "156";

	private $sign_method = "md5"; //摘要算法，目前仅支持md5 (2011-08-22)

	private $RESP_SUCCESS  = "00"; //返回成功

    private $QUERY_SUCCESS = "0";  //查询成功
    private $QUERY_FAIL    = "1";
    private $QUERY_WAIT    = "2";
    private $QUERY_INVALID = "3";


    /**
     * 构造函数

     *
     * @access  public
     * @param
     *
     * @return void
     */
    function unionpay()
    {
		$this->MYWWW = get_domain().get_redirect_url(get_app_url('respond/',array('code'=>'unionpay')));
		$this->Order = new Order;
    }

/*    function __construct()
    {
        $this->unionpay();
    }
*/
    /**
     * 生成支付代码
     * @param   array    $order       订单信息
     * @param   array    $payment     支付方式信息
     */
    function get_code($order, $payment)
    {
        /* 总金额 */
        $total_fee = floatval($order['order_amount']) * 100;

		$pay_params_mer  = array(
			'version'       => '1.0.0',
			'charset'       => 'UTF-8',            //UTF-8, GBK等
			'merId'         => $payment['merId'],  //商户填写
			'acqCode'       => '',                 //收单机构填写
			'merCode'       => '',                 //收单机构填写
			'merAbbr'       => $payment['merAbbr']
		);

        /* 交易参数 */
		$pay_params_order = array(
			'transType'          => $this->PRE_AUTH,         //交易类型，CONSUME or PRE_AUTH
			'commodityUrl'       => "",                      //商品URL
			'commodityName'      => $order['order_sn'],      //商品名称
			'commodityUnitPrice' => $total_fee,              //商品单价
			'commodityQuantity'  => 1,                       //商品数量
			'orderNumber'        => $order['order_sn'],      //订单号，必须唯一
			'orderAmount'        => $total_fee,              //交易金额
			'orderCurrency'      => $this->CURRENCY_CNY,     //交易币种，CURRENCY_CNY=>人民币
			'orderTime'          => date('YmdHis'),          //交易时间, YYYYmmhhddHHMMSS
			'customerIp'         => $_SERVER['REMOTE_ADDR'], //用户IP
			'frontEndUrl'        => $this->MYWWW,                      //前台回调URL
			'backEndUrl'         => $this->MYWWW                       //后台回调URL
		);

		$pay_params_empty = array(
			"origQid"           => "",
			"acqCode"           => "",
			"merCode"           => "",
			"commodityUrl"      => "",
			"commodityName"     => "",
			"commodityUnitPrice"=> "",
			"commodityQuantity" => "",
			"commodityDiscount" => "",
			"transferFee"       => "",
			"customerName"      => "",
			"defaultPayType"    => "",
			"defaultBankNumber" => "",
			"transTimeout"      => "",
			"merReserved"       => ""
		);

		$pay_params_check = array(
			"version",
			"charset",
			"transType",
			"origQid",
			"merId",
			"merAbbr",
			"acqCode",
			"merCode",
			"commodityUrl",
			"commodityName",
			"commodityUnitPrice",
			"commodityQuantity",
			"commodityDiscount",
			"transferFee",
			"orderNumber",
			"orderAmount",
			"orderCurrency",
			"orderTime",
			"customerIp",
			"customerName",
			"defaultPayType",
			"defaultBankNumber",
			"transTimeout",
			"frontEndUrl",
			"backEndUrl",
			"merReserved"
		);

		//商户保留域可能包含的字段
		$mer_params_reserved = array(
			//  NEW NAME            OLD NAME
			"cardNumber",       "pan",
			"cardPasswd",       "password",
			"credentialType",   "idType",
			"cardCvn2",         "cvn",
			"cardExpire",       "expire",
			"credentialNumber", "idNo",
			"credentialName",   "name",
			"phoneNumber",      "mobile",
			"merAbstract",

			//tdb only
			"orderTimeoutDate",
			"origOrderNumber",
			"origOrderTime",
		);


		//测试环境
		$api_url = "http://58.246.226.99/UpopWeb/api/Pay.action";
		//预上线环境
		//$api_url = "https://www.epay.lxdns.com/UpopWeb/api/Pay.action";
		//线上环境
		//$api_url = "https://unionpaysecure.com/api/Pay.action";

		$params = array_merge($pay_params_empty, $pay_params_order, $pay_params_mer);

		if (isset($params['commodityUrl'])) {
            $params['commodityUrl'] = $this->encodeURI($params['commodityUrl']);
        }

        //merReserved: 前后台支付、查询
        $has_reserved = false;
        $arr_reserved = array();
        foreach ($mer_params_reserved as $key) {
            if (isset($params[$key])) {
                $value = $params[$key];
                unset($params[$key]);
                $arr_reserved[] = "$key=$value";
                $has_reserved = true;
            }
        }
        if ($has_reserved) {
            $params['merReserved'] = sprintf("{%s}", join("&", $arr_reserved));
        } else {
            //请求一定有merReserved字段
            if (!isset($params['merReserved'])) {
                $params['merReserved'] = '';
            }
        }

        //param check
        foreach ($param_check as $key) {
            if (!isset($params[$key])) {
                throw new Exception("KEY [$key] not set in params given");
            }
        }

        //signature
        $params['signature']    = $this->sign($params, $this->sign_method, $payment);
        $params['signMethod']   = $this->sign_method;


		$html = <<<eot
    <form id="pay_form" name="pay_form" action="{$api_url}" method="post" target="_self" style="text-align:center;margin:0px;padding:0px" >
eot;
        foreach ($params as $key => $value) {
            $html .= "    <input type=\"hidden\" name=\"{$key}\" id=\"{$key}\" value=\"{$value}\" />\n";
        }
        $html .= '<input type="image" src="https://online.unionpay.com/static/portal/images/common/Logo.jpg" value="中国银联支付" /></form>';

        return $html;
    }

    /**
     * 响应操作
     */
    function respond()
    {
		$args = $_POST;
		$arr_args = array();
		$arr_reserved = array();
		if (is_array($args)) {
			$arr_args       = $args;
			$cupReserved    = isset($arr_args['cupReserved']) ? $arr_args['cupReserved'] : '';
			parse_str(substr($cupReserved, 1, -1), $arr_reserved); //去掉前后的{}
		} else {
			$cupReserved = '';
			$pattern = '/cupReserved=(\{.*?\})/';
			if (preg_match($pattern, $args, $match)) { //先提取cupReserved
				$cupReserved = $match[1];
			}
			//将cupReserved的value清除(因为含有&, parse_str没法正常处理)
			$args_r         = preg_replace($pattern, 'cupReserved=', $args);
			parse_str($args_r, $arr_args);
			$arr_args['cupReserved'] = $cupReserved;
			parse_str(substr($cupReserved, 1, -1), $arr_reserved); //去掉前后的{}
		}

		//提取服务器端的签名
		if (!isset($arr_args['signature']) || !isset($arr_args['signMethod'])) {
			throw new Exception('No signature Or signMethod set in notify data!');
		}
		$this->signMethod= $arr_args['signMethod'];
		unset($arr_args['signature']);
		unset($arr_args['signMethod']);

		$payment = $this->Order->get_payment($_GET['code']);

		//验证签名
		$signature = $this->sign($arr_args, $this->signMethod, $payment);
		if ($signature != $_POST['signature']) {
			throw new Exception('Bad signature returned!');
		}

		$args = array_merge($arr_args, $arr_reserved);
		unset($args['cupReserved']);

		$order_sn = $args['orderNumber'];
		$order_log_id = $this->Order->get_paylogid_by_orderid($order_sn);

		if($order_sn){
			$this->save_pay_log($order_log_id,"unionpay", $order_sn, $args);
		}

		//交易状态为1001表示交易成功，其他为各类错误，如卡内余额不足等
		$arr=array();
		if ($args['respCode'] == $this->RESP_SUCCESS){
			//您的处理逻辑请写在这里，如更新数据库等。
			//注意：如果您在提交时同时填写了页面返回地址和后台返回地址，且地址相同，请在这里先做一次数据库查询判断订单状态，以防止重复处理该笔订单

			if($order_sn = $this->Order->get_orderid_by_paylogid($order_log_id)){
				//如果买家付款成功，则等待买家发货，调用此接口
				$this->Order->order_paid($order_log_id,PS_PAYING);
				$arr['respond_flag']='success';
				$arr['order_sn']=$order_sn;
				return $arr;
			}else{
				$arr['respond_flag']='failed';
				return $arr;
			}
		} else {
			$arr['respond_flag']='failed';
			return $arr;
		}
    }

	function encodeURI($url)
    {
        if (preg_match("/^(.*?)\?(.*)/", $url, $match)) {
            $prefix = preg_replace("/\?.*/", "", $url);
            $query_string = $match[2];
            $arr_keqv = explode('&', $query_string);
            $arr_encoded = array();
            foreach ($arr_keqv as $keqv) {
                list($key, $value) = explode('=', $keqv);
                $arr_encoded[] = sprintf("%s=%s", $key, urlencode($value));
            }
            $query_string = join('&', $arr_encoded);
            return $prefix . '?' . $query_string;
        }
        else {
            return $url;
        }
    }

	function decodeURI($url)
    {
        if (preg_match("/^(.*?)\?(.*)/", $url, $match)) {
            $prefix = preg_replace("/\?.*/", "", $url);
            $query_string = $match[2];
            $arr_keqv = explode('&', $query_string);
            $arr_decoded = array();
            foreach ($arr_keqv as $keqv) {
                list($key, $value) = explode('=', $keqv);
                $arr_decoded[] = sprintf("%s=%s", $key, urldecode($value));
            }
            $query_string = join('&', $arr_decoded);
            return $prefix . '?' . $query_string;
        }
        else {
            return $url;
        }
    }

	function sign($params, $sign_method, $payment)
    {
		$sign_ignore_params = array("bank");

		$security_key = $payment['security_key']; //商户密钥

        if (strtolower($sign_method) == "md5") {
            ksort($params);
            $sign_str = "";
            foreach ($params as $key => $val) {
                if (in_array($key,$sign_ignore_params)) {
                    continue;
                }
                $sign_str .= sprintf("%s=%s&", $key, $val);
            }
            return md5($sign_str . md5($security_key));
        }
        /* TODO: elseif (strtolower($sign_method) == "rsa")  */
        else {
            throw new Exception("Unknown sign_method set in quickpay_conf");
        }
    }

}

?>